Imports Microsoft.Win32

Public Class MainForm
  Dim WithEvents _RecognitionContext As SpeechLib.SpSharedRecoContext

  Private _RemainingSeconds As Integer

  Const SPI_GETSPEECHRECOGNITION As Integer = &H104A
  Const WM_SETTINGCHANGE As Integer = &H1A

  Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" _
    (ByVal uAction As UInteger, ByVal uParam As UInteger, _
    <System.Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.Bool)> _
    ByRef lpvParam As Boolean, ByVal fuWinIni As UInteger) As Integer

#Region "Form events"

  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

    MyBase.WndProc(m)

    If m.Msg = WM_SETTINGCHANGE Then
      LoadSettings()
    End If

  End Sub

  Private Sub MainForm_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    If Me.WindowState <> FormWindowState.Minimized Then
      My.Settings.FormLocation = Me.Location
    End If

  End Sub

  Private Sub MainForm_HelpButtonClicked(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles Me.HelpButtonClicked
    Dim About As New AboutBox
    About.ShowDialog(Me)
    About.Dispose()
    About = Nothing

  End Sub

  Private Sub MainForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.Text += " [" & My.Application.Info.Version.ToString & "]"
    Me.NotifyIcon1.Visible = True

    LoadSettings()

    If My.Settings.MinimizeOnStartup Then
      Me.Visible = False
      Me.WindowState = FormWindowState.Minimized
    Else
      Me.Visible = True
      Me.WindowState = FormWindowState.Normal
    End If

    If My.Settings.FormLocation.IsEmpty = False Then
      Me.Location = My.Settings.FormLocation
    End If

  End Sub

  Private Sub MainForm_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
    If Me.WindowState = FormWindowState.Minimized Then
      Me.Visible = False
    End If
  End Sub

#End Region

#Region "Other form control events"

  Private Sub NotifyIcon1_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
    Me.Show()
    Me.WindowState = FormWindowState.Normal

  End Sub

  Private Sub ApplyButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ApplyButton.Click
    SaveSettings()
  End Sub

  Private Sub OkButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OkButton.Click
    SaveSettings()
    My.Settings.FormLocation = Me.Location
    Me.WindowState = FormWindowState.Minimized
  End Sub

  Private Sub CancelButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cancel.Click
    LoadSettings()
    My.Settings.FormLocation = Me.Location
    Me.WindowState = FormWindowState.Minimized
  End Sub

  Private Sub WaitTimeoutMinutesControl_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WaitTimeoutMinutesControl.ValueChanged, WaitTimeoutSecondsControl.ValueChanged
    Me.ApplyButton.Enabled = True
    If WaitTimeoutMinutesControl.Value = 0 AndAlso WaitTimeoutSecondsControl.Value = 0 Then
      WaitTimeoutMinutesControl.Value = 1
    End If
  End Sub

#End Region

#Region "Speech Lib methods and events"

  Private Sub ExecuteTimeout()

    _RecognitionContext.Recognizer.State = SpeechLib.SpeechRecognizerState.SRSInactiveWithPurge

  End Sub

  Private Sub RecognitionContext_RecognitionForOtherContext(ByVal StreamNumber As Integer, ByVal StreamPosition As Object) Handles _RecognitionContext.RecognitionForOtherContext
    ResetTimer()
  End Sub

  Private Sub RecognitionContext_RecognizerStateChange(ByVal StreamNumber As Integer, ByVal StreamPosition As Object, ByVal NewState As SpeechLib.SpeechRecognizerState) Handles _RecognitionContext.RecognizerStateChange

    Select Case NewState
      Case SpeechLib.SpeechRecognizerState.SRSActive
        ResetTimer()
      Case SpeechLib.SpeechRecognizerState.SRSActiveAlways
        ResetTimer()
      Case SpeechLib.SpeechRecognizerState.SRSInactive
        StopTimer()
      Case SpeechLib.SpeechRecognizerState.SRSInactiveWithPurge
        StopTimer()
    End Select
  End Sub

#End Region

#Region "Timer methods and events"

  Private Sub ResetTimer()
    Dim _WaitMinutes As Integer = 5
    Dim _WaitSeconds As Integer = 0

    _WaitMinutes = My.Settings.WaitTimeoutMinutes
    _WaitSeconds = My.Settings.WaitTimeoutSeconds
    _RemainingSeconds = (_WaitMinutes * 60) + _WaitSeconds
    TimeLeftLabel.Text = ConvertSecondstoCountdownTime(_RemainingSeconds)

    Me.Timer1.Enabled = True
  End Sub

  Private Sub StopTimer()
    Me.Timer1.Enabled = False
    TimeLeftLabel.Text = ""
  End Sub

  Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    _RemainingSeconds -= 1
    TimeLeftLabel.Text = ConvertSecondstoCountdownTime(_RemainingSeconds)

    If _RemainingSeconds <= 0 Then
      ExecuteTimeout()
      ResetTimer()
      StopTimer() 'This will already happen in RecognitionContext_RecognizerStateChange, but I want to be 100% clear, so doing it here too
    End If

  End Sub

#End Region

#Region "Misc helpers"

  Private Sub SaveSettings()
    My.Settings.WaitTimeoutMinutes = Me.WaitTimeoutMinutesControl.Value
    My.Settings.WaitTimeoutSeconds = Me.WaitTimeoutSecondsControl.Value

    My.Settings.MinimizeOnStartup = Me.MinOnStartupCheckBox.Checked
    My.Settings.Save()

    Me.ApplyButton.Enabled = False

    SetupTimerBaseOnSRState()

    If StartupWithWindowsCheckBox.Checked Then

      Dim RegKeyUser As RegistryKey = My.Computer.Registry.CurrentUser
      Dim RegKeyRun As RegistryKey = RegKeyUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
      RegKeyRun.SetValue("SpeechSaver", Application.ExecutablePath)
      RegKeyRun.Close()
      RegKeyUser.Close()

    Else
      Dim RegKeyUser As RegistryKey = My.Computer.Registry.CurrentUser
      Dim RegKeyRun As RegistryKey = RegKeyUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
      If RegKeyRun.GetValue("SpeechSaver", "").ToString.Length > 0 Then
        RegKeyRun.DeleteValue("SpeechSaver")
      End If
      RegKeyRun.Close()
      RegKeyUser.Close()

    End If

  End Sub

  Private Sub LoadSettings()
    Me.WaitTimeoutMinutesControl.Value = My.Settings.WaitTimeoutMinutes
    Me.WaitTimeoutSecondsControl.Value = My.Settings.WaitTimeoutSeconds
    Me.MinOnStartupCheckBox.Checked = My.Settings.MinimizeOnStartup

    Dim RegKeyUser As RegistryKey = My.Computer.Registry.CurrentUser
    Dim RegKeyRun As RegistryKey = RegKeyUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Run", True)
    StartupWithWindowsCheckBox.Checked = RegKeyRun.GetValue("SpeechSaver", "").ToString.Length > 0
    RegKeyRun.Close()
    RegKeyUser.Close()

    Me.ApplyButton.Enabled = False

    SetupTimerBaseOnSRState()

  End Sub

  Private Sub SetupTimerBaseOnSRState()
    Dim IsSRRunning As Boolean = False

    SystemParametersInfo(SPI_GETSPEECHRECOGNITION, 0, IsSRRunning, 0)

    If IsSRRunning = True Then
      'Hook up to the form scoped 
      If _RecognitionContext Is Nothing Then
        _RecognitionContext = New SpeechLib.SpSharedRecoContext
      End If

      'Setup initial Recognition state 
      ' i.e. If it's already "off" then stop the timer
      Select Case _RecognitionContext.Recognizer.State
        Case SpeechLib.SpeechRecognizerState.SRSInactive
          StopTimer()
        Case SpeechLib.SpeechRecognizerState.SRSInactiveWithPurge
          StopTimer()
        Case Else
          ResetTimer()

      End Select
    Else
      StopTimer()
      If _RecognitionContext IsNot Nothing Then
        _RecognitionContext = Nothing
      End If

    End If

  End Sub
  Private Function ConvertSecondstoCountdownTime(ByVal Seconds As Integer) As String

    Dim Result As String
    Dim Minutes As Integer
    Dim RemainingSeconds As Integer

    If Seconds < 60 Then
      Result = Seconds.ToString

    Else

      Minutes = Seconds \ 60

      RemainingSeconds = Seconds - (Minutes * 60)

      If RemainingSeconds < 10 Then
        Result = String.Format("{0:G}:0{1:G}", Minutes, RemainingSeconds)
      Else
        Result = String.Format("{0:G}:{1:G}", Minutes, RemainingSeconds)

      End If

    End If

    Return Result

  End Function

#End Region

#Region "Menu events"

  Private Sub PropertiesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PropertiesToolStripMenuItem.Click

    Me.Visible = True
    Me.Show()
    Me.WindowState = FormWindowState.Normal
    Me.BringToFront()

  End Sub

  Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click
    Me.Close()

  End Sub

#End Region

End Class
